package thread.ch04;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import thread.annotation.NotThreadSafe;

/**
 * 同步行为发生在错误的锁上。无论List使用哪个锁保护它的状态，可以确定的是这个锁并没用到ListHelper上。
 * <p />
 * ListHelper仅仅描绘了同步的幻象；即使一个list的操作全部声明为synchronized，但使用了不同锁，
 * 将意味着putIfAbsent对于List的其他操作而言，并不是原子化的。所以当putIfAbsent执行时，并不能保证另一个线程不会修改list。
 * <p />
 * 为了让这个方法正确工作，我们必须保证方法使用的锁，与List用于客户端加锁与外部加锁时所用的锁是同一个锁。
 * 客户端加锁必须保证客户端代码与对象x保护自己状态时使用的是相同的锁。为了正确执行客户端加锁，你必须知道x使用了哪个锁。
 * 
 * @author Edgar Zhang
 * 
 * @param <E>
 */
@NotThreadSafe
public class ListHelper<E> {

	public List<E> list = Collections.synchronizedList(new ArrayList<E>());

	public synchronized boolean putIfAbsent(E x) {
		boolean absent = !list.contains(x);
		if (absent) {
			list.add(x);
		}
		return absent;
	}

}
